#pragma once

#include "Action.h"

namespace My {

template <typename T, typename A>
class ChangeValueAction : public Action, public A {
public:
	typedef T ValueType;
	typedef A AccessType;
public:
	ChangeValueAction(const ValueType & v, const String & s, const AccessType & a = AccessType());
	virtual String GetCaption() const;
	virtual bool Execute();
	virtual void Unexecute();
	virtual void Reexecute();
protected:
	ValueType	m_Value;
	ValueType	m_Old;
	String		m_Caption;
};

template <typename T>
class VirtualValueAccess {
protected:
	virtual T Get() const = 0;
	virtual void Set(T v) = 0;
};

template <typename T>
class VirtualRefAccess {
protected:
	virtual const T & Get() const = 0;
	virtual void Set(const T & v) = 0;
};

template <typename C, typename T>
class ObjectValueAccess {
public:
	typedef C ClassType;
	typedef T ValueType;
	typedef T (C::* GetType)() const;
	typedef void (C::* SetType)(T);
public:
	ObjectValueAccess(C &, GetType, SetType);
	ValueType Get() const;
	void Set(ValueType v);
private:
	ClassType &	m_Object;
	GetType		m_Get;
	SetType		m_Set;
};

template <typename C, typename T>
class ObjectRefAccess {
public:
	typedef C ClassType;
	typedef T ValueType;
	typedef const T & RefType;
	typedef RefType (C::* GetType)() const;
	typedef void (C::* SetType)(RefType);
public:
	ObjectRefAccess(ClassType &, GetType, SetType);
	RefType Get() const;
	void Set(RefType v);
private:
	ClassType &	m_Object;
	GetType		m_Get;
	SetType		m_Set;
};

template <class C, class T>
Action * CreateChangeValue(
	C & object, 
	T (C::* get)() const, 
	void (C::* set)(T), 
	const T & value, 
	const String & caption);

template <class C, class T>
Action * CreateChangeValue(
	C & object, 
	const T & (C::* get)() const, 
	void (C::* set)(const T &), 
	const T & value, 
	const String & caption);

// Performs the ChangeValueAction
template <class C, class T>
void ChangeValue(
	C & object, 
	T (C::* get)() const, 
	void (C::* set)(T), 
	const T & value, 
	const String & caption);

// Performs the ChangeValueAction
template <class C, class T>
void ChangeValue(
	C & object, 
	const T & (C::* get)() const, 
	void (C::* set)(const T &), 
	const T & value, 
	const String & caption);

} // My

#include "Impl/StdActions.inl"
